package com.yjy.fuyao.stu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yjy.fuyao.stu.entity.*;
import com.yjy.fuyao.stu.entity.Course;
import com.yjy.fuyao.stu.entity.form.CourseInfo;
import com.yjy.fuyao.stu.entity.form.CommentInfo;
import com.yjy.fuyao.stu.entity.query.CourseQuery;
import com.yjy.fuyao.stu.entity.vo.CourseQueryVo;
import com.yjy.fuyao.stu.entity.vo.CourseWebVo;
import com.yjy.fuyao.stu.entity.vo.PublishCourseVo;
import com.yjy.fuyao.stu.entity.vo.RateCourseVo;
import com.yjy.fuyao.stu.mapper.CourseMapper;
import com.yjy.fuyao.stu.repository.EsCourseService;
import com.yjy.fuyao.stu.service.*;
import com.yjy.fuyao.stu.entity.Comment;
import com.yjy.fuyao.stu.entity.CourseDescription;
import com.yjy.fuyao.stu.service.*;
import com.yjy.fuyao.utils.exception.BusinessException;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author yjy
 * @since 2021-08-16
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    @Resource
    private EsCourseService esCourseService;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Resource
    private CourseDescriptionService courseDescriptionService;

    @Resource
    private VideoService videoService;

    @Resource
    private ChapterService chapterService;

    @Resource
    private CommentService commentService;

    @Override
    public String saveCourseInfo(CourseInfo courseInfo) {

        //保存课程基本信息
        Course course = new Course();
        course.setStatus(Course.COURSE_DRAFT);
        BeanUtils.copyProperties(courseInfo, course);
        boolean resultCourseInfo = this.save(course);
        if(!resultCourseInfo){
            throw new BusinessException("课程信息保存失败",20001);
        }

        //保存课程详情信息
        CourseDescription courseDescription = new CourseDescription();
        courseDescription.setDescription(courseInfo.getDescription());
        courseDescription.setId(course.getId());
        boolean resultDescription = courseDescriptionService.save(courseDescription);
        if(!resultDescription){
            throw new BusinessException("课程详情信息保存失败",20001);
        }
        return course.getId();
    }

    @Override
    public CourseInfo getCourseInfoById(String id) {
        Course course = baseMapper.selectById(id);
        CourseInfo courseInfo = new CourseInfo();
        BeanUtils.copyProperties(course,courseInfo);
        CourseDescription courseDescription = courseDescriptionService.getById(courseInfo.getId());
        courseInfo.setDescription(courseDescription.getDescription());
        return courseInfo;
    }

    @Override
    public PublishCourseVo getPublishCourseInfo(String id) {
        PublishCourseVo publishCourseVo = baseMapper.getPublishCourseInfo(id);
        return publishCourseVo;
    }

    @Override
    public boolean publishCourseById(String id) {
        Course course = new Course();
        course.setId(id);
        course.setStatus(Course.COURSE_NORMAL);
        Integer result = baseMapper.updateById(course);
        return result != null && result > 0;
    }

    @Override
    public IPage<Course> listPage(Page<Course> pageParam, CourseQuery courseQuery) {
        if(courseQuery == null){
            System.out.println("=========经过了listPage方法==========");
            return baseMapper.selectPage(pageParam,null);
        }
        String title = courseQuery.getTitle();
        String teacherId = courseQuery.getTeacherId();
        String subjectParentId = courseQuery.getSubjectParentId();
        String subjectId = courseQuery.getSubjectId();
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(title != null,"title", title)
                .eq(teacherId != null,"teacher_id", teacherId)
                .eq(subjectParentId != null,"subject_parent_id",subjectParentId)
                .eq(subjectId != null,"subject_id",subjectId);

        return baseMapper.selectPage(pageParam,queryWrapper);
    }

    @Override
    public boolean removeCourseById(String id) {
        videoService.removeByCourseId(id);
        chapterService.removeByCourseId(id);
        courseDescriptionService.removeByCourseId(id);
        baseMapper.deleteById(id);
        return true;
    }

    /**
     * 根据讲师id查询当前讲师的课程列表
     * @param teacherId
     * @return
     */
    @Override
    public List<Course> selectByTeacherId(String teacherId) {

        QueryWrapper<Course> queryWrapper = new QueryWrapper<Course>();

        queryWrapper.eq("teacher_id", teacherId);
        //按照最后更新时间倒序排列
        queryWrapper.orderByDesc("gmt_modified");

        List<Course> courses = baseMapper.selectList(queryWrapper);
        return courses;
    }



    @Override
    public Map<String, Object> pageListWeb(Page<Course> pageParam, CourseQueryVo courseQuery) {
        List<Course> records;
        long current,pages,size,total;
        boolean hasNext,hasPrevious;
        Map<String, Object> map = new HashMap<String, Object>();
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(courseQuery.getSubjectParentId())) {
            queryWrapper.eq("subject_parent_id", courseQuery.getSubjectParentId());
        }

        if (!StringUtils.isEmpty(courseQuery.getSubjectId())) {
            queryWrapper.eq("subject_id", courseQuery.getSubjectId());
        }

        if (!StringUtils.isEmpty(courseQuery.getBuyCountSort())) {
            queryWrapper.orderByDesc("buy_count");
        }

        if (!StringUtils.isEmpty(courseQuery.getGmtCreateSort())) {
            queryWrapper.orderByDesc("gmt_create");
        }

        if (!StringUtils.isEmpty(courseQuery.getPriceSort())) {
            queryWrapper.orderByDesc("price");
        }
        //使用ElasticSearch
        if (!StringUtils.isEmpty(courseQuery.getAboutCourse())) {
            NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.multiMatchQuery(courseQuery.getAboutCourse(), "title"))
                    .withSort(SortBuilders.fieldSort("gmtModified").order(SortOrder.DESC))
                    .withPageable(PageRequest.of((int) (pageParam.getCurrent() - 1), (int) pageParam.getSize()))
                    .build();
            org.springframework.data.domain.Page<Course> page = esCourseService
                    .search(searchQuery);
            records = page.getContent();
            current = page.getNumber();
            pages = page.getTotalPages();
            size = page.getSize();
            total = page.getTotalElements();
            hasNext = page.hasNext();
            hasPrevious = page.hasPrevious();
        } else {
            baseMapper.selectPage(pageParam, queryWrapper);

            records = pageParam.getRecords();
            current = pageParam.getCurrent();
            pages = pageParam.getPages();
            size = pageParam.getSize();
            total = pageParam.getTotal();
            hasNext = pageParam.hasNext();
            hasPrevious = pageParam.hasPrevious();
        }

        map.put("items", records);
        map.put("current", current);
        map.put("pages", pages);
        map.put("size", size);
        map.put("total", total);
        map.put("hasNext", hasNext);
        map.put("hasPrevious", hasPrevious);

        return map;
    }

    @Override
    public Map<String, Object> pageCollectWeb(Long page,Long limit, String userId) {
        long current,pages,size,total;
        boolean hasNext,hasPrevious;
        Map<String, Object> map = new HashMap<>();
        List<Course> collect = baseMapper.selectCollectByMid(userId,(page - 1)*limit,limit);
        current = page;
        pages = (collect.size() - 1) / limit + 1;
        size = limit;
        total = collect.size();
        hasNext = (page < total);
        hasPrevious = (page > 0);
        map.put("items", collect);
        map.put("current", current);
        map.put("pages", pages);
        map.put("size", size);
        map.put("total", total);
        map.put("hasNext", hasNext);
        map.put("hasPrevious", hasPrevious);

        return map;
    }

    @Override
    public CourseWebVo selectInfoWebById(String id) {
        Course course = baseMapper.selectById(id);
        CourseWebVo courseWebVo;
        if (course.getType() == 1) {
            courseWebVo = baseMapper.selectInfoWebById(id);
        } else {
            courseWebVo = baseMapper.selectInfoWebByIdu(id);
        }
        if(course.getRateCount() == 0) {
            courseWebVo.setRate(0.0);
        } else {
            BigDecimal rate = new BigDecimal(course.getRate().doubleValue() / course.getRateCount());
            courseWebVo.setRate(rate.setScale(1,1).doubleValue());
        }
        return courseWebVo;
    }

    @Override
    public void updatePageViewCount(String id) {
        Course course = baseMapper.selectById(id);
        course.setViewCount(course.getViewCount() + 1);
        baseMapper.updateById(course);
    }

    @Override
    public CourseInfo getCourseInfo(String courseId) {
        Course course = baseMapper.selectById(courseId);
        CourseInfo courseInfo = new CourseInfo();
        BeanUtils.copyProperties(course,courseInfo);
        return courseInfo;
    }

    @Override
    public boolean checkCourseById(String id, String checkResult) {
        Course course = new Course();
        course.setId(id);
        course.setStatus(checkResult);
        Integer result = baseMapper.updateById(course);
        return result != null && result > 0;
    }

    @Override
    public void addCourseRate(Long score, String courseId) {
        baseMapper.addCourseRate(score, courseId);
    }

    @Override
    public RateCourseVo rateForCourse(CommentInfo commentInfo) {
        Integer oldRate = commentInfo.getOldRate();
        Integer newRate = commentInfo.getRate();
        Comment comment = new Comment();
        BeanUtils.copyProperties(commentInfo,comment);
        if(commentInfo.getOldRate() != -1) {
            addCourseRate((long) (newRate - oldRate), commentInfo.getCourseId());
        } else {
            addCourseRate((long) (newRate), commentInfo.getCourseId());
        }
        commentService.saveOrUpdate(comment);
        //课程查询课程基本信息
        Course course = baseMapper.selectById(commentInfo.getCourseId());
        RateCourseVo rateCourseVo = new RateCourseVo();
        BigDecimal rate = new BigDecimal(course.getRate().doubleValue() / course.getRateCount());
        rateCourseVo.setRate(rate.setScale(1,1).doubleValue());
        rateCourseVo.setRateCount(course.getRateCount());
        rateCourseVo.setMyRate(commentInfo.getRate());
        rateCourseVo.setContent(commentInfo.getContent());
        return rateCourseVo;
    }

    @Override
    public Integer countNewCourseByDay(String day) {
        return baseMapper.selectNewCourseCount(day);
    }

}
